package edu.utn.tacs.grupouno.rest.implementations;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import edu.utn.tacs.grupouno.dao.TurnoContainer;
import edu.utn.tacs.grupouno.negocio.Analisis;
import edu.utn.tacs.grupouno.negocio.Dia;
import edu.utn.tacs.grupouno.negocio.DiaFactory;
import edu.utn.tacs.grupouno.negocio.EstadoTurno;
import edu.utn.tacs.grupouno.negocio.Turno;
import edu.utn.tacs.grupouno.negocio.TurnoSemanal;
import edu.utn.tacs.grupouno.rest.api.TurnoService;


@Service("turnoService")
@Path("/turno")
public class TurnoServiceImpl implements TurnoService {

	private DiaFactory factory;
	private static Logger logger = LoggerFactory.getLogger("edu.utn.tacs.grupouno.rest");
	/**
	 * Solo para probar
	 * TODO Hay que borrarlo
	 */
	
	
	public TurnoServiceImpl() {
	}
	
	@Override
	public List<Turno> getTurnos(String dateString) {
		try {
			List<Turno> turnos = getFactory().getDia(getDateFormat().parse(dateString)).getTurnos();
			for(Turno turno : turnos) {
				logger.debug("turno: " + turno);
			}
			return turnos;
		} catch (ParseException e) {
			logger.warn("Fecha invalida: " + dateString, e);
			throw new RuntimeException("Fecha invalida", e);
		}
	}

	@Override
	public Turno getTurno(String dateString, String time) {
		try {
			Date date = getDateFormat().parse(dateString);
			Dia dia = getFactory().getDia(date);
			Turno turno = dia.getTurno(time);
			logger.debug("turno: " + turno);
			return turno;
		} catch (ParseException e) {
			logger.warn("Fecha invalida: " + dateString, e);
			throw new RuntimeException("Fecha invalida", e);
		}
	}

	@Override
	public void setTurno(String dateString, Turno turno) {
		try {
			logger.info("Cargando nuevo turno. date: " + dateString + " turno: " + turno);
			Date date = getDateFormat().parse(dateString);
			Dia dia = getFactory().getDia(date);
			Turno turnoOriginal = dia.getTurno(turno.getHorario());
			if(turnoOriginal == null) {
				throw new RuntimeException("Horario no disponible para asignar un turno");
			}
			if(!turnoOriginal.isDisponible()) {
				getTurnoContainer().liberarTurno(date, turnoOriginal);
				logger.warn("El turno estaba ocupado. Replazado.");
			}
			getTurnoContainer().addTurnoAsignado(date, turno);
		} catch (ParseException e) {
			logger.warn("Fecha invalida: " + dateString, e);
			throw new RuntimeException("Fecha invalida", e);
		}
	}
	
	@Override
	public void setTurno(String dateString, String time, Turno turno) {
		try {
			logger.info("Cargando nuevo turno. date: " + dateString + " time:" + time + " turno: " + turno);
			Date date = getDateFormat().parse(dateString);
			Dia dia = getFactory().getDia(date);
			Turno turnoOriginal = dia.getTurno(time);
			if(turnoOriginal == null) {
				throw new RuntimeException("Horario no disponible para asignar un turno");
			}
			if(!time.equals(turno.getHorario())) {
				throw new RuntimeException("El turno no tiene el horario que indica la URL");
			}
			if(!turnoOriginal.isDisponible()) {
				getTurnoContainer().liberarTurno(date, turnoOriginal);
			}
			getTurnoContainer().addTurnoAsignado(date, turno);
		} catch (ParseException e) {
			logger.warn("Fecha invalida: " + dateString, e);
			throw new RuntimeException("Fecha invalida", e);
		}
	}
	
	@Override
	public void removeTurno(String dateString, String time) {
		try {
			logger.info("Liberando turno " + dateString + " " + time);
			Date date = getDateFormat().parse(dateString);
			Dia dia = getFactory().getDia(date);
			Turno turnoOriginal = dia.getTurno(time);
			if(turnoOriginal == null) {
				return;
			}
			if(!turnoOriginal.isDisponible()) {
				getTurnoContainer().liberarTurno(date, turnoOriginal);
				logger.info("Turno liberado");
			}
		} catch (ParseException e) {
			logger.warn("Fecha invalida: " + dateString, e);
			throw new RuntimeException("Fecha invalida", e);
		}
	}
	
	@Override
	public DateFormat getDateFormat() {
		return new SimpleDateFormat("dd-MM-yyyy");
	}
	
	@Override
	public void asistioPaciente(String date, String time, EstadoTurno estado) {
		Turno turno = getTurno(date, time);
		if(turno != null) {
			turno.setEstado(estado);
		}
	}
	
	@Override
	public void asignarAnalisis(String date, String time, Analisis analisis) {
		try {
			logger.info("asignarTurno( date: " + date + ", time: " + time + ", analisisId: " + analisis.getId() + ")");
			Turno turno = getTurno(date, time);
			if(turno != null && turno.isDisponible()) {
				turno.asignar(analisis);
				getTurnoContainer().addTurnoAsignado(getDateFormat().parse(date), turno);
				logger.info("asignarTurno     [ OK ]");
			} else {
				logger.error("El turno no existe o no esta disponible.");
				throw new WebApplicationException(404);
			}
		} catch (ParseException e) {
			throw new RuntimeException("Fecha invalida", e);
		}
	}
	
	@Override
	public void addTurnoSemanal(TurnoSemanal turnoSemanal) {
		logger.info("addTurnoSemanal( " + turnoSemanal + " )");
		getTurnoContainer().addTurnoSemanal(turnoSemanal);
		logger.info("addTurnoSemanal    [ OK ]");
	}
	
	///////////////////////////////////////////////////////////////////////////
	
	private TurnoContainer getTurnoContainer() {
		return getFactory().getTurnoContainer();
	}
	
	@Autowired
	public void setFactory(DiaFactory factory) {
		this.factory = factory;
	}
	
	public DiaFactory getFactory() {
		return factory;
	}

}
